package com.power.sifa.approve.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.aventrix.jnanoid.jnanoid.NanoIdUtils;
import com.plf.common.domain.ResponseDTO;
import com.plf.common.domain.YesNo;
import com.plf.common.exception.BusinessException;
import com.plf.common.file.service.IFileService;
import com.plf.common.utils.PdfConvertUtil;
import com.plf.common.utils.StringUtil;
import com.plf.common.utils.WordUtil;
import com.plf.core.base.model.EnumerationHelper;
import com.plf.core.base.model.Ha_attachment;
import com.plf.core.base.service.Ha_attachmentService;
import com.power.flowable.api.IPersonalFeign;
import com.power.sifa.approve.dao.Apl_applicantDao;
import com.power.sifa.approve.dao.Apl_dossierDao;
import com.power.sifa.approve.dao.BusinessApproveDao;
import com.power.sifa.approve.executor.AdmreExecutor;
import com.power.sifa.approve.model.*;
import com.power.sifa.approve.model.doc.AbstractDoc;
import com.power.sifa.approve.model.doc.DocFactory;
import com.power.sifa.approve.model.doc.HearAuditDelayDoc;
import com.power.sifa.approve.model.enumeration.*;
import com.power.sifa.approve.model.pojo.vo.ProcessVariablesVo;
import com.power.sifa.approve.service.*;
import com.power.sifa.net.model.ProcessInfo;
import com.power.sifa.net.model.enumeration.Tp_matter;
import com.power.sifa.net.service.ApplyService;
import com.power.sifa.supervise.model.Apl_supervise;
import com.power.sifa.supervise.service.Apl_superviseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
@Slf4j
public class BusinessApproveServiceImpl extends AdmreExecutor implements BusinessApproveService {

//    @Resource
//    private BusinessApproveService service;
    @Resource
    private IPersonalFeign iPersonalFeign;
    @Resource
    private Apl_mainService apl_mainService;
    @Resource
    private Apl_admreviewService apl_admreviewService;
    @Resource
    private Apl_admre_auditService apl_admre_auditService;
    @Resource
    private ApplyService applyService;
    @Resource
    private Aprv_process_materialsService aprv_process_materialsService;
    @Resource
    private Ha_attachmentService ha_attachmentService;
    @Resource
    private Apl_limit_hearService apl_limit_hearService;
    @Resource
    private Apl_limdelay_hearService apl_limdelay_hearService;
    @Resource
    private Apl_applicantDao apl_applicantDao;
    @Resource
    private EnumerationHelper helper;
    @Resource
    private Apl_dossierDao apl_dossierDao;
    @Resource
    private Apl_archiveService apl_archiveService;
    @Resource
    private Cloud_sign_licenseService cloud_sign_licenseService;
    @Resource
    private BusinessApproveDao businessApproveDao;
    @Resource
    private IFileService fileService;
    @Resource
    private Apl_decision_recordService apl_decision_recordService;

    @Resource
    private Apl_superviseService apl_superviseService;


    private static final Map<String, XWPFRun.FontCharRange> FONT_RANGE;

    private static final String SIGN_TEXT = "（用印）";

    static {
        FONT_RANGE = new HashMap<>();
        FONT_RANGE.put("仿宋_GB2312", XWPFRun.FontCharRange.eastAsia);
        FONT_RANGE.put("Times New Roman", XWPFRun.FontCharRange.cs);
    }


    @Override
    public Map<String, String> startBusinessProced(String applyid, String proctype, String userid, String username, String processinstanceid, String cause, String describe, Map<String, Object> docfield) throws Exception {
        synchronized (applyid) {

            Tp_proctypeEnum proctypeEnum = Tp_proctypeEnum.getByKey(proctype);
            Map<String, String> result;
            Map<String, Object> variableMap = new HashMap<>(16);
            // 是否市领导审批
            Integer isCitymanager = ObjectUtil.isNotNull(docfield.get("isCitymanager")) ? Integer.parseInt(docfield.get("isCitymanager").toString()) : 3201;
            String soninstid;
            /**
             * 受理环节
             */
            switch (proctypeEnum.getId()) {
                case Tp_proctype.MATER_MEDIATE:
                case Tp_proctype.ACCEPT_ACCEPT:
                case Tp_proctype.ACCEPT_APPEND:
                case Tp_proctype.ACCEPT_INFORM:
                case Tp_proctype.ACCEPT_NOACCEPT:
                case Tp_proctype.ACCEPT_RESULT:
                case Tp_proctype.ACCEPT_OTHERDEAL: {
                    result = this.acceptBusiness(applyid, proctypeEnum, userid, username, cause, describe, docfield, isCitymanager);
                    soninstid = result.get("processinstanceid");
                    break;
                }
                case Tp_proctype.ACCEPT_CHANGE_FIRSTPER: {
                    // 变更承办人
                    if (StringUtil.isEmpty(docfield.get("acceptfirstid")) || StringUtil.isEmpty(docfield.get("acceptfirstname"))) {
                        log.error("startBusinessProced 流程业务变量缺失");
                        throw new RuntimeException("流程业务变量缺失");
                    }
                    variableMap.put("acceptfirstid", docfield.get("acceptfirstid"));
                    variableMap.put("acceptfirstname", docfield.get("acceptfirstname"));
                    result = this.acceptBusiness(applyid, proctypeEnum, userid, username, cause, describe, docfield, isCitymanager);
                    soninstid = result.get("processinstanceid");
                    break;
                }
                case Tp_proctype.ACCEPT_CHANGE_SECONDPER: {
                    // 变更协办人
                    if (StringUtil.isEmpty(docfield.get("acceptsecondid")) || StringUtil.isEmpty(docfield.get("acceptsecondname"))) {
                        log.error("startBusinessProced 流程业务变量缺失");
                        throw new RuntimeException("流程业务变量缺失");
                    }
                    variableMap.put("acceptsecondid", docfield.get("acceptsecondid"));
                    variableMap.put("acceptsecondname", docfield.get("acceptsecondname"));
                    result = this.acceptBusiness(applyid, proctypeEnum, userid, username, cause, describe, docfield, isCitymanager);
                    soninstid = result.get("processinstanceid");
                    break;
                }
                case Tp_proctype.HEAR_DECISION: {
                    // 决定
                    if (StringUtil.isEmpty(docfield.get("decisiontypeid")) || StringUtil.isEmpty(docfield.get("decisiontypename")) || StringUtil.isEmpty(docfield.get("decisiontype"))) {
                        log.error("startBusinessProced 流程业务变量缺失");
                        throw new RuntimeException("流程业务变量缺失");
                    }
                    variableMap.put("decisiontype", docfield.get("decisiontype"));
                    variableMap.put("decisiontypeid", docfield.get("decisiontypeid"));
                    variableMap.put("decisiontypename", docfield.get("decisiontypename"));
                    result = this.hearBusiness(applyid, proctypeEnum, userid, username, cause, describe, docfield, isCitymanager);
                    soninstid = result.get("processinstanceid");
                    break;
                }
                case Tp_proctype.HEAR_CHANGE_FIRTPER: {
                    // 审理变更承办人
                    if (StringUtil.isEmpty(docfield.get("hearfirstid")) || StringUtil.isEmpty(docfield.get("hearfirstname"))) {
                        log.error("startBusinessProced 流程业务变量缺失");
                        throw new RuntimeException("流程业务变量缺失");
                    }
                    variableMap.put("hearfirstid", docfield.get("hearfirstid"));
                    variableMap.put("hearfirstname", docfield.get("hearfirstname"));
                    result = this.hearBusiness(applyid, proctypeEnum, userid, username, cause, describe, docfield, isCitymanager);
                    soninstid = result.get("processinstanceid");
                    break;

                }
                case Tp_proctype.HEAR_CHANGE_SECONDPER: {
                    // 审理变更承办人
                    if (StringUtil.isEmpty(docfield.get("hearsecondid")) || StringUtil.isEmpty(docfield.get("hearsecondname"))) {
                        log.error("startBusinessProced 流程业务变量缺失");
                        throw new RuntimeException("流程业务变量缺失");
                    }
                    variableMap.put("hearsecondid", docfield.get("hearsecondid"));
                    variableMap.put("hearsecondname", docfield.get("hearsecondname"));
                    result = this.hearBusiness(applyid, proctypeEnum, userid, username, cause, describe, docfield, isCitymanager);
                    soninstid = result.get("processinstanceid");
                    break;
                }
                default: {
                    /**
                     * 审理 | 执行环节
                     */
                    result = this.hearBusiness(applyid, proctypeEnum, userid, username, cause, describe, docfield, isCitymanager);
                    soninstid = result.get("processinstanceid");
                }
            }
            // 1.1 启动成功后给市领导审批变量赋值
            // 是否第市领导审批
            variableMap.put(ProcessVariablesVo.CITYAPPROVE, isCitymanager);
            try {
                ResponseDTO res = this.iPersonalFeign.saveVariable(soninstid, variableMap);
                if (0 != res.getCode()) {
                    throw new RuntimeException(res.getMsg());
                }
            } catch (Exception e) {
                log.error("startBusinessProced 设置子流程分支变量失败->  msg[{}]", e.getMessage());
                throw new RuntimeException("设置子流程分支变量失败");
            }
            return result;
        }
    }

    /**
     * 受理子流程业务操作
     *
     * @param applyid
     * @param proctypeEnum
     * @param userid
     * @param username
     * @param cause
     * @param describe
     * @param docfield
     * @return
     * @throws ParseException
     * @throws BusinessException
     */
    private Map<String, String> acceptBusiness(String applyid, Tp_proctypeEnum proctypeEnum, String userid, String username, String cause, String describe, Map<String, Object> docfield, Integer isCitymanager) throws ParseException, BusinessException {

        Apl_admreview admreviewObj = this.apl_admreviewService.getById(applyid);
        Apl_main faMainObj = this.apl_mainService.getById(applyid);
        Apl_main mainObj = this.apl_mainService.createMain(userid, proctypeEnum.getProcesskey(), faMainObj, Tp_matter.PUB_ADMREVIEW);

        // 校验父流程是否挂起
        ResponseDTO isSupRes = this.iPersonalFeign.isSuspended(faMainObj.getInstid());
        if (0 != isSupRes.getCode()) {
            throw new RuntimeException("查询父流程是否挂起失败");
        }
        Boolean isSup = (Boolean) isSupRes.getData();
        if (isSup) {
            throw new RuntimeException("已存在其他的子流程");
        }


        // 调解在单独的调解菜单, 单独修改状态
        Integer statusapply;
        if (Tp_proctype.MATER_MEDIATE == proctypeEnum.getId()) {
            statusapply = St_admreview.TOMEDIATE;
        } else {
            statusapply = St_admreview.UNDO;
        }

        // 1. 启动一个子流程
        String processinstanceid = this.createSonProcess(faMainObj, mainObj, admreviewObj, userid, describe, statusapply, proctypeEnum.getId(), isCitymanager, YesNo.NO);
        // 2. 挂起父流程
        try {
            ResponseDTO res = this.iPersonalFeign.suspendProcess(faMainObj.getInstid());
            if (0 != res.getCode()) {
                throw new RuntimeException(res.getMsg());
            }
        } catch (Exception e) {
            log.error("acceptBusiness 挂起父流程失败->  msg[{}]", e.getMessage());
        }

        // 3. 查询子流程的taskid前端自动跳转
        ResponseDTO resTask = this.iPersonalFeign.queryTaskidByInstid(processinstanceid);
        log.info("acceptBusiness 执行成功 -> 子流程: {}", processinstanceid);
        Map<String, String> result = new HashMap<>(16);
        result.put("processinstanceid", processinstanceid);
        if (0 == resTask.getCode()) {
            result.put("taskid", (String) resTask.getData());
            return result;
        }
        return result;

    }

    /**
     * 审理子流程业务操作
     *
     * @param applyid
     * @param proctypeEnum
     * @param userid
     * @param username
     * @param cause
     * @param describe
     * @param docfield
     * @return
     * @throws Exception
     */
    private Map<String, String> hearBusiness(String applyid, Tp_proctypeEnum proctypeEnum, String userid, String username, String cause, String describe, Map<String, Object> docfield, Integer isCitymanager) throws Exception {
        Apl_admreview admreviewObj = this.apl_admreviewService.getById(applyid);
        // 校验是否存在协办人
        if (StringUtil.isEmpty(admreviewObj.getHearsecondid())) {
            log.error("hearBusiness 请先分派协办人" + proctypeEnum.getName());
            throw new RuntimeException("请先分派协办人");
        }
        // 校验是否已经存在相同的子流程
        if (this.checkSonStatus(admreviewObj.getSonstatus(), proctypeEnum.getStatus())) {
            log.error("hearBusiness 已存在正在审批的" + proctypeEnum.getName());
            throw new RuntimeException("已存在正在审批的" + proctypeEnum.getName());
        }
        if (null == proctypeEnum) {
            throw new RuntimeException("hearBusiness 流程模型key为空");
        }

        // 延期必须要有延期天数, 先校验
        if (Tp_proctypeEnum.HEAR_DELAY.getStatus().equals(proctypeEnum.getStatus()) && null == docfield.get("daySize")) {
            log.error("hearBusiness 延期天数不能为空");
            throw new RuntimeException("延期日期不能为空");
        } else if (Tp_proctypeEnum.HEAR_DECISION.getStatus().equals(proctypeEnum.getStatus()) && null == docfield.get("decisiontype")) {
            log.error("hearBusiness 决定类型不能为空");
            throw new RuntimeException("决定类型不能为空");
        }

        Apl_main faMainObj = this.apl_mainService.getById(applyid);
        // 校验是否支持程序转换, 普通程序转简易程序如超过30日不能发起
        if (Tp_proctypeEnum.HEAR_TRANSFORM.getStatus().equals(proctypeEnum.getStatus()) && Tp_apptype.ORDINARY == admreviewObj.getProctype()) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Date accepttime = format.parse(faMainObj.getAccepttime());
            long days = (new Date().getTime() - accepttime.getTime()) / (24 * 3600 * 1000);
            if (days > 30) {
                log.error("hearBusiness 普通程序转简易程序超过30日");
                throw new RuntimeException("普通程序转简易程序超过30日");
            }
        }
        Apl_main mainObj = this.apl_mainService.createMain(userid, proctypeEnum.getProcesskey(), faMainObj, Tp_matter.PUB_ADMREVIEW);
        // 1. 启动一个子流程
        String processinstanceid = this.createSonProcess(faMainObj, mainObj, admreviewObj, userid, describe, St_admreview.ACCEPT, proctypeEnum.getId(), isCitymanager, YesNo.NO);
        // 3. 更新父流程的子状态
        String sonStatus = this.addSonStatus(admreviewObj.getSonstatus(), proctypeEnum.getStatus());
        this.apl_admreviewService.updatesSonStatus(admreviewObj.getId(), sonStatus);
        // 4. 自动生成可生成的业务过程材料 (事前生成后续注释)
//        docfield.put("cause", cause);
//        docfield.put("describe", describe);
//        this.createMaterialByProctype(proctypeEnum.getKey(), procid, admreviewObj, userid, username, faMainObj.getFormid(), docfield);
        // 5. 如果是延期审批, 先产生一条延期记录
        if (Tp_proctypeEnum.HEAR_DELAY.getStatus().equals(proctypeEnum.getStatus())) {
            Integer extensionday = Integer.valueOf(docfield.get("daySize").toString());
            String reason = (String) docfield.get("reason");
            this.createExtensionday(applyid, mainObj.getId(), userid, extensionday, reason);
        } else if (Tp_proctypeEnum.HEAR_DECISION.getStatus().equals(proctypeEnum.getStatus())) {
            Integer decisiontype = ObjectUtil.isNotNull(docfield.get("decisiontype")) ? (Integer) docfield.get("decisiontype") : null;
            Integer decisiontypeid = ObjectUtil.isNotNull(docfield.get("decisiontypeid")) ? (Integer) docfield.get("decisiontypeid") : null;
            String decisiontypename = ObjectUtil.isNotNull(docfield.get("decisiontypename")) ? (String) docfield.get("decisiontypename") : null;
            // 对应子表记录也更新一条
            Apl_admre_audit auditObj = this.apl_admre_auditService.getById(mainObj.getId());
            auditObj.setDecisiontype(decisiontype);
            auditObj.setDecisiontypeid(decisiontypeid);
            auditObj.setDecisiontypename(decisiontypename);
            this.apl_admre_auditService.saveOrUpdate(auditObj);
            // 更新干预行政复议活动记录表数据
            this.apl_decision_recordService.updateDecisionRecords(applyid, mainObj.getId());
        }
        // 6. 查询子流程的taskid前端自动跳转
        ResponseDTO resTask = this.iPersonalFeign.queryTaskidByInstid(processinstanceid);
        log.info("hearBusiness 执行成功 -> 子流程: {}", processinstanceid);
        Map<String, String> result = new HashMap<>(16);
        result.put("processinstanceid", processinstanceid);
        if (0 == resTask.getCode()) {
            result.put("taskid", (String) resTask.getData());
            return result;
        }
        return result;
    }

    /**
     * 创建保存一个子流程
     *
     * @param faMainObj
     * @param mainObj
     * @param admreviewObj
     * @param userid
     * @param describe
     * @param status
     * @param procType
     * @param isCitymanager
     * @return
     * @throws BusinessException
     * @throws ParseException
     */
    @Override
    public String createSonProcess(Apl_main faMainObj, Apl_main mainObj, Apl_admreview admreviewObj, String userid, String describe, Integer status, Integer procType, Integer isCitymanager, Integer isSecondOut) throws ParseException, BusinessException {
        // 1. 启动一个子流程
        ResponseDTO res = this.iPersonalFeign.startSonProcess(faMainObj.getInstid(), mainObj.getId(), userid, mainObj.getFormid(), null, new HashMap<>(16));
        if (0 != res.getCode()) {
            log.error("startBusinessProced 启动子流程失败 -> msg[{}]", res.getMsg());
            throw new BusinessException(res.getMsg());
        }
        ProcessInfo processObj = JSON.parseObject(JSON.toJSONString(res.getData()), ProcessInfo.class);
        mainObj.setInstid(processObj.getProcessinstanceid());
        mainObj.setScatid(processObj.getScatid());
        mainObj.setAcceptcode(faMainObj.getAcceptcode());
        this.apl_mainService.saveOrUpdate(mainObj);

        // 2. 通过父流程applyid, 查询生成子流程业务表数据
        Apl_admre_audit auditObj = new Apl_admre_audit();
        auditObj.setId(mainObj.getId());
        auditObj.setType(procType);
        auditObj.setCode(faMainObj.getAcceptcode());
        auditObj.setApplyid(faMainObj.getId());
        auditObj.setReason(apl_admreviewService.getReason(admreviewObj.getPrtype()));
        auditObj.setApplyname(admreviewObj.getApplyname());
        auditObj.setTargetname(admreviewObj.getTargetname());
        // 提交日期为收到日期
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat formatT = new SimpleDateFormat("yyyy年M月d日");
        auditObj.setReceiptdate(formatT.format(format.parse(faMainObj.getSubtime())));
        // auditObj.setFirstremark(describe);
        auditObj.setIstargetreply(admreviewObj.getIstargetreply());
        auditObj.setIsrest(admreviewObj.getIsrest());
        auditObj.setIsmediate(admreviewObj.getIsmediate());
        auditObj.setIsomission(admreviewObj.getIsomission());
        auditObj.setPrtype(admreviewObj.getPrtype());
        auditObj.setThirdper(admreviewObj.getThirdname());
        auditObj.setMgrcate(admreviewObj.getMgrcate());
        auditObj.setProctype(admreviewObj.getProctype());
        auditObj.setIsdelay(admreviewObj.getIsdelay());
        auditObj.setAdmrequest(apl_admreviewService.getAdmreReason(admreviewObj));
        auditObj.setAcceptfirstid(admreviewObj.getAcceptfirstid());
        auditObj.setAcceptfirstname(admreviewObj.getAcceptfirstname());
        auditObj.setAcceptsecondid(admreviewObj.getAcceptsecondid());
        auditObj.setAcceptsecondname(admreviewObj.getAcceptsecondname());
        auditObj.setHearfirstid(admreviewObj.getHearfirstid());
        auditObj.setHearfirstname(admreviewObj.getHearfirstname());
        auditObj.setHearsecondid(admreviewObj.getHearsecondid());
        auditObj.setHearsecondname(admreviewObj.getHearsecondname());
        // 第三人信息
        auditObj.setThirdper(super.queryThirdper(faMainObj.getId()));
        // 是否市领导审批
        auditObj.setIscitymanager(isCitymanager);
        // 是否已经市领导审批
        auditObj.setIssecondout(isSecondOut);

        // 计算期满日期, 受理根据提交时间算, 审理根据受理时间算5天
        String quedateStr;
        if (faMainObj.getAccepttime() != null) {
            quedateStr = this.computeExpiryDate(admreviewObj.getProctype(), faMainObj.getAccepttime());
            auditObj.setAcceptdate(formatT.format(format.parse(faMainObj.getAccepttime())));
        } else {
            quedateStr = this.businessApproveDao.expiryDate(format.parse(faMainObj.getSubtime()), 5);
        }
        auditObj.setQuedate(new SimpleDateFormat("yyyy年M月d日").format(format.parse(quedateStr)));

        // 行政复议审批表类型状态
        auditObj.setStatus(status);
        this.apl_admre_auditService.saveOrUpdate(auditObj);
        return processObj.getProcessinstanceid();
    }

    /**
     * 记录一条延期记录
     *
     * @param applyid
     * @param extensionday
     */
    private void createExtensionday(String applyid, String sonapplyid, String userid, Integer extensionday, String reason) throws ParseException {

        // 1. 查询受理产生的审理时限记录
        Apl_limit_hear hearOri = apl_limit_hearService.getById(applyid);
        String extensiondate = this.businessApproveDao.expiryDate(hearOri.getEnddate(), extensionday);
        if (null == hearOri) {
            log.error("createExtensionday 查询受理产生的审理时限记录失败");
            throw new RuntimeException("查询受理产生的审理时限记录失败");
        }

        Apl_limdelay_hear hearNew = new Apl_limdelay_hear();
        hearNew.setId(System.currentTimeMillis() + applyid);
        hearNew.setApplyid(applyid);
        hearNew.setSonapplyid(sonapplyid);
        hearNew.setEndtime0(hearOri.getEnddate());
        hearNew.setEnddate1(new SimpleDateFormat("yyyy-MM-dd").parse(extensiondate));
        hearNew.setReason(reason);
        hearNew.setUserid(userid);
        // 延期了多少天
        this.apl_limdelay_hearService.saveOrUpdate(hearNew);
    }

    @Override
    public String addSonStatus(String sonStatus, Integer status) {
        if (null == sonStatus) {
            return ObjectUtil.isNotNull(status) ? status.toString() : "";
        }
        List<String> list = Arrays.stream(StringUtils.split(sonStatus, ",")).collect(Collectors.toList());
        if (ObjectUtil.isNotNull(status)) {
            list.add(status.toString());
        }
        return StringUtils.join(list, ",");
    }

    @Override
    public String delSonStatus(String sonStatus, Integer status) {
        if (null == sonStatus) {
            return null;
        }
        List<String> list = Arrays.stream(StringUtils.split(sonStatus, ",")).collect(Collectors.toList());
        for (int i = list.size() - 1; i >= 0; i--) {
            if (list.get(i).equals(status.toString())) {
                list.remove(i);
                break;
            }
        }
        return StringUtils.join(list, ",");
    }

    @Override
    public Boolean checkSonStatus(String sonStatus, Integer status) {
        if (null == sonStatus) {
            return false;
        }
        List<String> list = Arrays.stream(StringUtils.split(sonStatus, ",")).collect(Collectors.toList());
        return CollectionUtil.isNotEmpty(list) ? list.contains(status.toString()) : Boolean.FALSE;
    }

    @Override
    public Apl_admre_audit createThreeLevelApprove(String applyid, String userid, String username, Integer type) throws Exception {
        // 1. 查询子流程的表单数据
        Apl_main mainObj = this.apl_mainService.getById(applyid);
        Apl_admre_audit auditObj = this.apl_admre_auditService.getById(applyid);
        Map<String, Object> formData = this.applyService.formLoadField(mainObj.getFormid(), applyid);
        Apl_admreview admreObj = this.apl_admreviewService.getById(auditObj.getApplyid());
        formData.put("apl_admreview_hearsecondname", admreObj.getHearsecondname());
        super.ApprovalField(formData);
        // 2. 生成并上传文件
        Ha_attachment attachment;
        byte[] pdfByte;
        WordUtil wordUtil = new WordUtil("ThreeLevelApprove.docx");
        wordUtil.replaceTable(formData);
        try (OutputStream os = wordUtil.createWord();
             InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray())) {
            pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            attachment = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), "行政复议案件审批表.pdf");
            log.info("generateThreeLevelApprove 三级审批文书生成并保存成功 -> {}", attachment.getId());
        } catch (Exception e) {
            log.error("generateThreeLevelApprove 三级审批文书生成并保存失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("generateThreeLevelApprove 三级审批文书生成并保存失败 -> " + e.getMessage());
        }

        // 2. 保存审批系统文书, 只存父流程
        Aprv_process_materials docObj = new Aprv_process_materials(Tp_procmaterialEnum.ADMRE_REPORT);
        docObj.setId(applyid + NanoIdUtils.randomNanoId());
        // 通知书类型枚举
        docObj.setMattype(Tp_procmaterial.ADMRE_REPORT);
        docObj.setAttachid(attachment.getId());
        docObj.setCreateuserid(userid);
        docObj.setCreateuser(username);
        docObj.setCreatetime(new Date());
        docObj.setApplyid(auditObj.getApplyid());
        docObj.setType(type);
        this.aprv_process_materialsService.saveOrUpdate(docObj);

        return auditObj;

    }


    /**
     * 自动生成过程材料
     *
     * @param proctype
     * @param procid
     * @param admreObj
     * @param userid
     * @param username
     * @param formid
     * @param docfield
     * @throws Exception
     */
    void createMaterialByProctype(String proctype, Integer procid, Apl_admreview admreObj, String userid, String username, String formid, Map<String, Object> docfield) throws Exception {

        // 找出能自动生成的材料列表
        List<Tp_procmaterialEnum> matList = new ArrayList<>(10);

        if (proctype.equals(Tp_proctypeEnum.HEAR_HEARING.getKey())) {
            matList.add(Tp_procmaterialEnum.HEAR_HEARING);
        } else if (proctype.equals(Tp_proctypeEnum.HEAR_STOP.getKey())) {
            matList.add(Tp_procmaterialEnum.HEAR_STOP);
        } else if (proctype.equals(Tp_proctypeEnum.HEAR_DELAY.getKey())) {
            matList.add(Tp_procmaterialEnum.HEAR_DELAY);
        } else if (proctype.equals(Tp_proctypeEnum.HEAR_REST.getKey())) {
            // 要中止
            if (YesNo.NO == admreObj.getIsrest()) {
                matList.add(Tp_procmaterialEnum.HEAR_HANGUP);
            } else {
                // 要恢复
                matList.add(Tp_procmaterialEnum.HEAR_RESTORE);
            }
        } else if (proctype.equals(Tp_proctypeEnum.HEAR_DECISION.getKey())) {
            // 根据决定操作添加对应字段和材料
            Integer decisiontype = (Integer) docfield.get("decisiontype");
            Tp_procmaterialEnum emum = this.decisionOperate(admreObj.getId(), decisiontype, docfield);
            if (null != emum) {
                matList.add(emum);
            }
            // TODO 后续调整
        } else if (proctype.equals(Tp_proctypeEnum.EXECUTE_FORCE_UNIT.getKey())) {
            //  (先注释) matList.add(Tp_procmaterialEnum.ARRIVE_FORCE);
        } else if (proctype.equals(Tp_proctypeEnum.EXECUTE_FORCE_LAW.getKey())) {
            //  (先注释) matList.add(Tp_procmaterialEnum.HEAR_REMINDER);
        } else if (proctype.equals(Tp_proctypeEnum.EXECUTE_PERFORM.getKey())) {
            //  (先注释) matList.add(Tp_procmaterialEnum.HEAR_PERFORM);
        } else if (proctype.equals(Tp_proctypeEnum.EXECUTE_SELF.getKey())) {
            //  (先注释) matList.add(Tp_procmaterialEnum.ARRIVE_PUNISH);
        }
        if (CollectionUtils.isEmpty(matList)) {
            return;
        }

        // 1. 查询表单数据
        Map<String, Object> formData = this.applyService.formLoadField(formid, admreObj.getId());
        // 1.1 设置申请表字段
        for (Map.Entry<String, Object> entry : docfield.entrySet()) {
            formData.put(entry.getKey(), entry.getValue());
        }

        // 2. 设置公共字段
        Apl_main mainObj = this.apl_mainService.getById(admreObj.getId());
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat formatT = new SimpleDateFormat("yyyy年M月d日");
        // 2.1 申请日期
        formData.put("applydate", formatT.format(format.parse(mainObj.getSubtime())));
        formData.put("acceptcode", mainObj.getAcceptcode());
        // 2.2 中止日期
        if (!StringUtil.isEmpty(admreObj.getRestdate())) {
            formData.put("restdate", formatT.format(format.parse(admreObj.getRestdate())));
        }
        // 2.3 当前日期
        formData.put("today", formatT.format(new Date()));
        // 2.4 行政行为
        if (YesNo.YES == admreObj.getIsomission()) {
            formData.put("behavior", "不履行法定职责");
        } else {
            if (Tp_admpr.OTHER.getKey() == admreObj.getPrtype()) {
                formData.put("behavior", admreObj.getPrname());
            } else {
                formData.put("behavior", Tp_admpr.getByKey(admreObj.getPrtype()).getDescription());
            }
        }
        // 2.5 申请主体 你（你们或你单位）
        List<Apl_applicant> applist = this.apl_applicantDao.getByApplyid(admreObj.getId());
        if (CollectionUtils.isEmpty(applist)) {
            throw new BusinessException("createMaterialByProctype 申请人为空");
        }
        if (applist.size() > 1) {
            formData.put("applybody", "你们");
        } else {
            if (Tp_agent.LEGAL == applist.get(0).getType()) {
                formData.put("applybody", "你单位");
            } else {
                formData.put("applybody", "你");
            }
        }

        // 3. 生成并保存过程材料
        for (Tp_procmaterialEnum file : matList) {
            this.createMaterial(admreObj.getId(), procid, userid, username, file, formData);
        }

    }

    /**
     * 决定操作过程材料的字段逻辑
     *
     * @param applyid
     * @param docfield
     * @return
     */
    private Tp_procmaterialEnum decisionOperate(String applyid, Integer decisiontype, Map<String, Object> docfield) {
        // (终止-其它)操作
        if (Tp_decision.TEROTHER == decisiontype) {
            // 法定代表人或者主要负责人信息
            List<Apl_applicant> applist = this.apl_applicantDao.getByApplyid(applyid);
            List<String> tempList = new ArrayList<>(10);
            for (Apl_applicant v : applist) {
                if (YesNo.YES == v.getIsrepr()) {
                    tempList.add(v.getName());
                }
            }
            if (!CollectionUtils.isEmpty(tempList)) {
                docfield.put("decisiontype", StringUtils.join(tempList, "，"));
            } else {
                docfield.put("decisiontype", "");
            }
            // 第三人信息
            docfield.put("thirdper", super.queryThirdper(applyid));

            return Tp_procmaterialEnum.HEAR_TERMIN;

        } else if (Arrays.asList(Tp_decision.PROREJECT, Tp_decision.SUBREJECT, Tp_decision.MAINTAIN, Tp_decision.BREAKLAW, Tp_decision.CHANGE, Tp_decision.ORDER).contains(decisiontype)) {
            StringBuilder applystr = new StringBuilder();
            // 申请人
            if (null != docfield.get("applylist")) {
                List<Apl_applicant> applist = JSON.parseArray(JSON.toJSONString(docfield.get("applylist")), Apl_applicant.class);
                for (Apl_applicant v : applist) {
                    applystr.append("申请人：");
                    applystr.append(v.getName());
                    if (null != v.getGender()) {
                        applystr.append("，" + helper.getDescription(v.getGender()));
                    }
                    if (null != v.getNation()) {
                        applystr.append("，" + helper.getDescription(v.getNation()));
                    }
                    if (null != v.getBirthym()) {
                        applystr.append("，" + v.getBirthym());
                    }
                    if (null != v.getAddr()) {
                        applystr.append("，" + v.getAddr());
                    }
                    applystr.append("\n" + "    ");
                }
            }
            // 法人或者其他组织
            if (null != docfield.get("aplentlist")) {
                List<Apl_applicant> aplentlist = JSON.parseArray(JSON.toJSONString(docfield.get("aplentlist")), Apl_applicant.class);
                if (!CollectionUtils.isEmpty(aplentlist)) {
                    for (Apl_applicant v : aplentlist) {
                        applystr.append("申请人（法人或者其他组织）：");
                        applystr.append(v.getName());
                        if (null != v.getAddr()) {
                            applystr.append("，" + v.getAddr());
                        }
                        if (null != v.getManager()) {
                            applystr.append("，" + v.getManager());
                        }
                        if (null != v.getJob()) {
                            applystr.append("，" + v.getJob());
                        }
                        applystr.append("\n" + "    ");
                    }
                }
            }
            // 被申请人
            applystr.append("被申请人：");
            applystr.append(docfield.get("targetlist"));
            applystr.append("\n" + "    ");
            // 第三人
            if (null != docfield.get("thirdperlist")) {
                List<Apl_thirdper> thilist = JSON.parseArray(JSON.toJSONString(docfield.get("thirdperlist")), Apl_thirdper.class);
                for (Apl_thirdper v : thilist) {
                    applystr.append("第三人：");
                    applystr.append(v.getName());
                    if (null != v.getAddr()) {
                        applystr.append("，" + v.getAddr());
                    }
                    applystr.append("\n" + "    ");
                }
            }
            docfield.put("applystr", applystr.toString());
            if (Arrays.asList(Tp_decision.PROREJECT, Tp_decision.SUBREJECT).contains(decisiontype)) {
                return Tp_procmaterialEnum.HEAR_REJECT;
            } else {
                return Tp_procmaterialEnum.HEAR_DECISION;
            }
        }
        return null;
    }

    public void createMaterial(String applyid, Integer procid, String userid, String username, Tp_procmaterialEnum file, Map<String, Object> formData) throws Exception {
        Ha_attachment attachment;
        byte[] pdfByte;
        WordUtil wordUtil = new WordUtil(file.getFilename());
        wordUtil.replaceParams(formData);
        try (OutputStream os = wordUtil.createWord();
             InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());) {

            pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            attachment = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), file.getDesc() + ".pdf");
            log.info("createMaterial " + file.getFilename() + "生成并保存成功 -> {}", attachment.getId());
        } catch (Exception e) {
            log.error("createMaterial " + file.getFilename() + "生成并保存失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("createMaterial " + file.getFilename() + "生成并保存失败 ->" + e.getMessage());
        }
        // 3. 保存审批过程材料, 只存父流程
        Aprv_process_materials matObj = new Aprv_process_materials(file);
        matObj.setId(applyid + NanoIdUtils.randomNanoId());
        // 通知书类型枚举
        matObj.setType(procid);
        matObj.setMattype(file.getId());
        matObj.setAttachid(attachment.getId());
        matObj.setCreateuserid(userid);
        matObj.setCreateuser(username);
        matObj.setCreatetime(new Date());
        matObj.setApplyid(applyid);
        this.aprv_process_materialsService.saveOrUpdate(matObj);

    }

    @Override
    public Date getTargetDay(Date date, int days) {
        return this.businessApproveDao.getTargetDay(date, days);
    }

    @Override
    public InputStream previewDecisionDoc(String applyid, String proctype, Map<String, Object> docfield) throws Exception {
        Apl_main mainObj = this.apl_mainService.getById(applyid);
        if (null == mainObj) {
            throw new RuntimeException("mainObj为null");
        }
        Apl_admreview admreObj = this.apl_admreviewService.getById(applyid);
        if (null == admreObj) {
            throw new RuntimeException("admreObj为null");
        }
        // 找出能自动生成的材料列表
        Tp_procmaterialEnum matEnum = null;

        if (proctype.equals(Tp_proctypeEnum.HEAR_HEARING.getKey())) {
            matEnum = Tp_procmaterialEnum.HEAR_HEARING;
        } else if (proctype.equals(Tp_proctypeEnum.HEAR_STOP.getKey())) {
            matEnum = Tp_procmaterialEnum.HEAR_STOP;
        } else if (proctype.equals(Tp_proctypeEnum.HEAR_DELAY.getKey())) {
            matEnum = Tp_procmaterialEnum.HEAR_DELAY;
        } else if (proctype.equals(Tp_proctypeEnum.HEAR_REST.getKey())) {
            // 要中止
            if (YesNo.NO == admreObj.getIsrest()) {
                matEnum = Tp_procmaterialEnum.HEAR_HANGUP;
            } else {
                // 要恢复
                matEnum = Tp_procmaterialEnum.HEAR_RESTORE;
            }
        } else if (proctype.equals(Tp_proctypeEnum.HEAR_DECISION.getKey())) {
            // 根据决定操作添加对应字段和材料
            Integer decisiontype = (Integer) docfield.get("decisiontype");
            Tp_procmaterialEnum emum = this.decisionOperate(admreObj.getId(), decisiontype, docfield);
            if (null != emum) {
                matEnum = emum;
            }
        }
        if (null == matEnum) {
            return null;
        }

        // 1. 查询表单数据
        Map<String, Object> formData = this.applyService.formLoadField(mainObj.getFormid(), admreObj.getId());
        // 1.1 设置申请表字段
        for (Map.Entry<String, Object> entry : docfield.entrySet()) {
            formData.put(entry.getKey(), entry.getValue());
        }

        // 2. 设置公共字段
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat formatT = new SimpleDateFormat("yyyy年M月d日");
        // 2.1 申请日期
        formData.put("applydate", formatT.format(format.parse(mainObj.getSubtime())));
        formData.put("acceptcode", mainObj.getAcceptcode());
        // 2.2 中止日期
        if (!StringUtil.isEmpty(admreObj.getRestdate())) {
            formData.put("restdate", formatT.format(format.parse(admreObj.getRestdate())));
        }
        // 2.3 当前日期
        formData.put("today", formatT.format(new Date()));
        // 2.4 行政行为
        if (YesNo.YES == admreObj.getIsomission()) {
            formData.put("behavior", "不履行法定职责");
        } else {
            if (Tp_admpr.OTHER.getKey() == admreObj.getPrtype()) {
                formData.put("behavior", admreObj.getPrname());
            } else {
                formData.put("behavior", Tp_admpr.getByKey(admreObj.getPrtype()).getDescription());
            }
        }

        WordUtil wordUtil = new WordUtil(matEnum.getFilename());
        wordUtil.replaceParams(formData);
        try (OutputStream os = wordUtil.createWord();
             InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray())) {
            return is;
        } catch (Exception e) {
            log.error("previewDecisionDoc " + applyid + "生成并保存失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("previewDecisionDoc " + applyid + "生成并保存失败 ->" + e.getMessage());
        }
    }

    /**
     * 行政复议的封面生成
     */
    private Ha_attachment createAdmerviewArchiveCover(String applyid, Map<String, Object> formData) throws Exception {
        // 2. 查询主表作出的决定类型
        Apl_admreview admObj = this.apl_admreviewService.getById(applyid);
        if (ObjectUtil.isNotEmpty(admObj.getDecisiontype())) {
            // 复议结果
            formData.put("result", helper.getDescription(admObj.getDecisiontype()));
        }
        // 案由
        formData.put("reason", this.apl_admreviewService.getAdmreReason(admObj));
        // 案件承办人 (第一立案审查人, 第二立案审查人), 先取审理的承办人值, 没有取受理的承办人值
        if (!StringUtil.isEmpty(admObj.getHearfirstname())) {
            formData.put("handlername", !StringUtil.isEmpty(admObj.getHearsecondname()) ? admObj.getHearfirstname() + "，" + admObj.getHearsecondname() : admObj.getHearfirstname());
        } else if (!StringUtil.isEmpty(admObj.getAcceptfirstname())) {
            formData.put("handlername", !StringUtil.isEmpty(admObj.getAcceptsecondname()) ? admObj.getAcceptfirstname() + "，" + admObj.getAcceptsecondname() : admObj.getAcceptfirstname());
        }
        // 第三人
        formData.put("thirdper", super.queryThirdper(applyid));

        // 2. 当前日期
        SimpleDateFormat formatT = new SimpleDateFormat("yyyy年M月d日");
        formData.put("today", formatT.format(new Date()));
        Ha_attachment attObj;
        WordUtil wordUtil = new WordUtil("ArchiveCover.docx");
        wordUtil.replaceTable(formData);
        try (OutputStream os = wordUtil.createWord();
             InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray())) {

            byte[] pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            attObj = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), "案卷封面.pdf");
        } catch (Exception e) {
            log.error("生成案卷封面失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("生成案卷封面失败" + e.getMessage());
        }
        return attObj;
    }

    /**
     * 复议监督的封面生成
     * @param applyid
     * @param formData
     * @return
     */
    private Ha_attachment createSuperviseArchiveCover(String applyid, Map<String, Object> formData) {
        // 2. 查询主表作出的决定类型
        Apl_supervise superviseObj = this.apl_superviseService.getById(applyid);
        // 事项信息
        formData.put("matinfo", superviseObj.getMatinfo());
        // 案件承办人
        if (!StringUtil.isEmpty(superviseObj.getFirstname())) {
            formData.put("handlername", !StringUtil.isEmpty(superviseObj.getFirstname()) ? superviseObj.getFirstname() + "，" + superviseObj.getSecondname() : superviseObj.getSecondname());
        }
        // 案件辅助人
        formData.put("supportname",  superviseObj.getThirdname());
        // 2. 当前日期
        SimpleDateFormat formatT = new SimpleDateFormat("yyyy年M月d日");
        formData.put("today", formatT.format(new Date()));
        Ha_attachment attObj;
        OutputStream os = null;
        InputStream is = null;
        try {
            WordUtil wordUtil = new WordUtil("ArchiveCoverSupervise.docx");
            wordUtil.replaceTable(formData);
            os = wordUtil.createWord();
            is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());
            byte[] pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            attObj = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), "案卷封面.pdf");
        } catch (Exception e) {
            log.error("生成案卷封面失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("生成案卷封面失败" + e.getMessage());
        } finally {
            try {
                if (null != is) {
                    is.close();
                }
                if (null != os) {
                    os.close();
                }
            } catch (IOException e) {
                log.error("生成案卷封面，关闭流失败 ->  msg[{}]", e.getMessage());
            }
        }
        return attObj;
    }
    @Override
    public Ha_attachment createArchiveCover(String applyid, Integer serviceType) throws Exception {
        // 1. 查询归档记录
        Apl_archive acrObj = this.apl_archiveService.getById(applyid);
        if (null == acrObj) {
            log.error("createArchiveCover 归档记录不存在");
        }
        Map<String, Object> formData = JSON.parseObject(JSON.toJSONString(acrObj), Map.class);
        if (St_servicetType.REVIEW == serviceType) {
            return createAdmerviewArchiveCover(applyid, formData);
        } else if(St_servicetType.SUPERVISE == serviceType) {
            return createSuperviseArchiveCover(applyid, formData);
        }
        return null;
    }

    @Override
    public Ha_attachment createArchiveDirectory(String applyid, Integer serviceType) {
        Ha_attachment attObj;
        OutputStream os = null;
        InputStream is = null;
        try {
            Map<String, Map> tableData = new HashMap<>(16);
            // 目录结构只要卷项
            List<Apl_dossier> dosList = this.apl_dossierDao.getByApplyid(applyid, Tp_dostype.TERM);
            if (!CollectionUtils.isEmpty(dosList)) {
                Map data = new HashMap();
                int i = 1;
                List<Object[]> list = new ArrayList<>(dosList.size());
                dosList = dosList.stream().filter(p -> p.getStartindex() != null).collect(Collectors.toList());
                Collections.sort(dosList, (o1, o2) -> o1.getStartindex() > o2.getStartindex() ? 1 : -1);
                for (Apl_dossier v : dosList) {
                    // 排除三项基本文件
                    if (v.getMattype() == null || v.getMattype().equals(String.valueOf(Tp_mattype.COVER)) || v.getMattype().equals(String.valueOf(Tp_mattype.DIRECTORY)) || v.getMattype().equals(String.valueOf(Tp_mattype.FILINGS))) {
                        continue;
                    }
                    list.add(new Object[]{i, v.getName(), v.getStartindex().equals(v.getEndindex()) ? v.getEndindex() : v.getStartindex() + "-" + v.getEndindex()});
                    i++;
                }
                data.put("list", list);
                tableData.put("fileList", data);
            }
            WordUtil wordUtil;
            if (St_servicetType.REVIEW == serviceType) {
                wordUtil = new WordUtil("ArchiveDirectory.docx");
            } else {
                wordUtil = new WordUtil("ArchiveDirectorySupervise.docx");
            }
            wordUtil.insertTable(tableData);
            os = wordUtil.createWord();
            is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());
            byte[] pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            attObj = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), "卷内目录.pdf");
        } catch (Exception e) {
            log.error("生成卷内目录失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("生成卷内目录失败" + e.getMessage());
        }
        return attObj;
    }

    @Override
    public Ha_attachment createArchiveBackCover(String applyid) {
        Ha_attachment attObj;
        OutputStream os = null;
        InputStream is = null;
        try {
            // 1. 查询归档记录
            Apl_archive acrObj = this.apl_archiveService.getById(applyid);
            if (null == acrObj) {
                log.error("createArchiveBackCover 归档记录不存在");
                throw new RuntimeException("归档记录不存在");
            }
            Map<String, Object> tableData = JSON.parseObject(JSON.toJSONString(acrObj), Map.class);
            // 2. 当前日期
            SimpleDateFormat formatT = new SimpleDateFormat("yyyy年M月d日");
            tableData.put("today", formatT.format(new Date()));
            WordUtil wordUtil = new WordUtil("ArchiveBackCover.docx");
            wordUtil.replaceTable(tableData);
            os = wordUtil.createWord();
            is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());
            byte[] pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            attObj = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), "行政复议案件备考表（封底）.pdf");
        } catch (Exception e) {
            log.error("生成行政复议案件备考表（封底）失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("生成行政复议案件备考表（封底）失败" + e.getMessage());
        } finally {
            try {
                if (null != is) {
                    is.close();
                }
                if (null != os) {
                    os.close();
                }
            } catch (IOException e) {
                log.error("生成行政复议案件备考表（封底）关闭流失败 ->  msg[{}]", e.getMessage());
            }
        }
        return attObj;
    }

    @Override
    public InputStream previewDocByDocName(String applyid, Integer materilaType, Map<String, Object> docfield) throws Exception {
        // 判断当前的材料类型
        Tp_procmaterialEnum materialEnum = Tp_procmaterialEnum.getById(materilaType);
        if (ObjectUtil.isNull(materialEnum)) {
            throw new BusinessException("当前材料类型为空");
        }
        String docName = materialEnum.getFilename();
        if (StringUtils.isEmpty(docName)) {
            throw new BusinessException("当前材料类型为空");
        }
        // 延期审理通知书
        if (Tp_procmaterialEnum.HEAR_DELAY.getId().equals(materilaType)) {
            HearAuditDelayDoc auditDelayDoc = new HearAuditDelayDoc();
            auditDelayDoc.transDate(docfield);
        }
        WordUtil wordUtil = new WordUtil(docName);
        wordUtil.replaceParamsWithFontSetting(docfield, FONT_RANGE);
        try (OutputStream os = wordUtil.createWord();
             InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray())) {
            return is;
        } catch (Exception e) {
            log.error("预览文件保存为pdf失败 ->  msg[{}]", e.getMessage());
            throw new BusinessException("预览文件保存为pdf失败" + e.getMessage());
        }
    }


    /**
     * 预览文件保存为pdf返回
     *
     * @param applyid
     * @return
     */
    @Override
    public Ha_attachment previewDocSaveToPdf(String applyid, Integer materilaType, Map<String, Object> docfield) throws Exception {
        // 判断当前的材料类型
        Tp_procmaterialEnum materialEnum = Tp_procmaterialEnum.getById(materilaType);
        if (ObjectUtil.isNull(materialEnum)) {
            throw new BusinessException("当前材料类型为空");
        }
        String docName = materialEnum.getFilename();
        if (StringUtils.isEmpty(docName)) {
            throw new BusinessException("当前材料类型为空");
        }
        Ha_attachment attachment;
        byte[] pdfByte;
        WordUtil wordUtil = new WordUtil(docName);
        wordUtil.replaceParamsWithFontSetting(docfield, FONT_RANGE);
        try (OutputStream os = wordUtil.createWord();
             InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray())) {
//            pdfByte = word2pdf(is);
            pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            String fileName = materialEnum.getDesc() + ".pdf";
//            attachment = ha_attachmentService.upload(is, fileName);
            attachment = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), fileName);
            log.info(docName + "-预览文件生成成功 -> {}", attachment.getId());
        } catch (Exception e) {
            log.error(docName + "-预览文件生成pdf失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException(docName + "-预览文件生成pdf失败 -> " + e.getMessage());
        }
        return attachment;
    }

    /**
     * 行政复议预览业务字段
     */
    private void approvalPreview(String applyid, Map<String, Object> formData) throws ParseException {
        // 日期转换
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat formatT = new SimpleDateFormat("yyyy年M月d日");
        if (null != formData.get("apl_admre_audit_firstdate")) {
            formData.put("apl_admre_audit_firstdate", formatT.format(format.parse((String) formData.get("apl_admre_audit_firstdate"))));
        }

        // -- 处理承办人显示名字, 其他全部清除 --
        formData.put("apl_admre_audit_secondname", "");
        formData.put("apl_admre_audit_seconddate", "");
        formData.put("apl_admre_audit_thirdname", "");
        formData.put("apl_admre_audit_thirddate", "");

        // 查询第三人信息
        Apl_admre_audit auditObj = this.apl_admre_auditService.getById(applyid);
        formData.put("apl_admre_audit_thirdper", super.queryThirdper(auditObj.getApplyid()));
    }

    private void buildCorrectionImg(WordUtil wordUtil, Map<String, Object> formData) {
        if (ObjectUtil.isNotNull(formData) && formData.containsKey("apl_condeploy_person_avatar")
                && StringUtils.isNotEmpty(formData.get("apl_condeploy_person_avatar").toString())) {
            final String avater = formData.get("apl_condeploy_person_avatar").toString();
            if (StringUtils.isNotEmpty(avater)) {
                Map<String, WordUtil.Img> imgMap = new HashMap<>();
                List<String> attachMentId = new ArrayList<>(10);
                attachMentId.add(avater);
                Map<String, Ha_attachment> ha_attachmentMap = ha_attachmentService.getHa_attachmentMapByIds(attachMentId);
                Ha_attachment attachment2 = ha_attachmentMap.get(avater);
                try {
                    InputStream photoInputStream = fileService.getStream(attachment2.getBucket(), attachment2.getPath());
                    String fileType = attachment2.getFilename().substring(attachment2.getFilename().lastIndexOf("."));
                    File tempFile = File.createTempFile(attachment2.getId(), fileType);

                    if (ObjectUtil.isNotNull(photoInputStream)) {
                        byte[] photoByte = IOUtils.toByteArray(photoInputStream);
                        FileOutputStream fos = null;
                        try {
                            fos = new FileOutputStream(tempFile);
                            fos.write(photoByte);
                        } catch (IOException e) {
                            log.error("图片流转换异常 {}", e.getMessage());
                        } finally {
                            fos.close();
                        }
                    }
                    FileInputStream fileInputStream = new FileInputStream(tempFile);
                    WordUtil.Img img = wordUtil.new Img(fileInputStream, 65, 86);
                    imgMap.put("avatar", img);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                wordUtil.replaceTableImg(imgMap);
            }
        }
    }

    @Override
    public Ha_attachment previewApproveDoc(String applyid, String modelKey, Map<String, Object> body) {
        try {
            // 1. 查询子流程的表单数据
            Map<String, Object> formData = new HashMap<>(16);
            for (String key : body.keySet()) {
                List<Map<String, Object>> vlaueList = (List<Map<String, Object>>) body.get(key);
                if (!CollectionUtils.isEmpty(vlaueList)) {
                    for (Map<String, Object> v : vlaueList) {
                        formData.put(key + "_" + v.get("field"), v.get("value"));
                    }
                }
            }


            // 根据流程模型key转换对应审批表
            String filename;
            WordUtil wordUtil = null;
            switch (modelKey) {
                case "ADMRE_AUDIT_APPEND":
                case "ADMRE_AUDIT_MEDIATE":
                case "ADMRE_AUDIT_ACCEPT":
                case "ADMRE_AUDIT_INFORM":
                case "ADMRE_AUDIT_NOACCEPT":
                case "ADMRE_AUDIT_WITHDRAW":
                case "ADMRE_AUDIT_OTHERDEAL":
                case "ACCEPT_CHANGE": {
                    this.approvalPreview(applyid, formData);
                    filename = "AdmreAuditInCharge.docx";
                    wordUtil = new WordUtil(filename);
                    break;
                }
                case "HEAR_MEDIATE":
                case "HEAR_SURVEY":
                case "HEAR_INQUEST":
                case "HEAR_HEARING":
                case "HEAR_IDENTIFY":
                case "HEAR_STOP":
                case "HEAR_DELAY":
                case "HEAR_REST":
                case "HEAR_DECISION":
                case "HEAR_WITHDRAW":
                case "HEAR_MOBILIZE":
                case "HEAR_RESTORE":
                case "HEAR_TRANSFORM":
                case "HEAR_EXPERT":
                case "EXECUTE_FORCE":
                case "EXECUTE_REMINDER":
                case "EXECUTE_PERFORM":
                case "EXECUTE_PUNISH": {
                    this.approvalPreview(applyid, formData);
                    filename = "ThreeLevelApprove.docx";
                    wordUtil = new WordUtil(filename);
                    break;
                }
                case "PUB_CORRECTION": {
                    super.CorrectionField(formData);
                    filename = "CorrectionCondeploy.docx";
                    wordUtil = new WordUtil(filename);
                    buildCorrectionImg(wordUtil, formData);
                    break;
                }
                case "SUPERVISE_DECISION": {
                    this.approvalPreview(applyid, formData);
                    filename = "SuperviseDecisionCheck.docx";
                    wordUtil = new WordUtil(filename);
                    break;
                }
                default: {
                    log.error("previewApproveDoc 未定义的流程预览材料");
                    throw new RuntimeException("未定义的流程预览材料");
                }
            }

            byte[] pdfByte;
            // -----------
//            Map<String, WordUtil.Img> imgMap = new HashMap<>();
//            List<String> attachMentId = new ArrayList<>(10);
//            attachMentId.add("lp5PHCoWRzmLdKl18uYzR");
//            Map<String, Ha_attachment> ha_attachmentMap = ha_attachmentService.getHa_attachmentMapByIds(attachMentId);
//            Ha_attachment attachment2 = ha_attachmentMap.get("lp5PHCoWRzmLdKl18uYzR");
//            try {
//                InputStream photoInputStream = fileService.getStream(attachment2.getBucket(), attachment2.getPath());
//                String fileType = ".png";
//                File tempFile = File.createTempFile(attachment2.getId(), fileType);
//
//                if (ObjectUtil.isNotNull(photoInputStream)) {
//                    byte[] photoByte = IOUtils.toByteArray(photoInputStream);
//                    FileOutputStream fos = null;
//                    try {
//                        fos = new FileOutputStream(tempFile);
//                        fos.write(photoByte);
//                    } catch (IOException e) {
//                        log.error("图片流转换异常 {}", e.getMessage());
//                    } finally {
//                        fos.close();
//                    }
//                }
//                FileInputStream fileInputStream = new FileInputStream(tempFile);
//                WordUtil.Img img = wordUtil.new Img(fileInputStream);
//                imgMap.put("avatar", img);
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//            wordUtil.replaceTableImg(imgMap);
            // ------------
            wordUtil.replaceTable(formData);
            OutputStream os = wordUtil.createWord();
            InputStream is = new ByteArrayInputStream(((ByteArrayOutputStream) os).toByteArray());
            pdfByte = PdfConvertUtil.word2pdfWithFont(is);
            Ha_attachment attachment = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), "临时预览文件.pdf");
            Map<String, Ha_attachment> attachmentMap = ha_attachmentService.getHa_attachmentsByIds(Arrays.asList(attachment.getId()));
            Ha_attachment transAttachment = attachmentMap.get(attachment.getId());
            // 启动子线程删除对应文件数据
            CompletableFuture.runAsync(() -> {
                try {
                    // 休眠30秒钟后删除该文件
                    Thread.sleep(30000);
                    ha_attachmentService.removeById(transAttachment.getId());
                    boolean deleteFlag = fileService.removeFile(attachment.getBucket(), attachment.getPath());
                    log.info("等待30秒删除临时文件:{}", deleteFlag);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            });
            return transAttachment;
        } catch (Exception e) {
            log.error("previewApproveDoc 预览审批文书失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("预览审批文书失败 -> " + e.getMessage());
        }
    }

    /**
     * 拼接对应的生成文书的参数
     *
     * @param applyid
     * @return
     * @throws Exception
     */
    @Override
    public AbstractDoc initBeforeProcess(String applyid, Integer materilaType) throws Exception {
        DocFactory factory = new DocFactory();
        AbstractDoc doc = factory.createDoc(applyid, materilaType);
        AbstractDoc template = doc.generateTemplate(applyid);
        return template;
    }

    /**
     * 当前流程走完后更新对应的文件数据
     *
     * @param applyid
     * @param proctype
     * @param decisionType
     */
    @Override
    public void processEndedUpdatePreviewDoc(String applyid, Integer proctype, Integer decisionType) {
        // FIXME: 之前用于表单编辑预览，后被在线编辑替代 执行空方法，避免超时，后续功能回调再放开
//        try {
//            Tp_proctypeDocEnum docEnum;
//            // 获取对应的材料配置
//            if (Tp_proctype.HEAR_DECISION == proctype) {
//                docEnum = Tp_proctypeDocEnum.getByDecisionType(decisionType);
//            } else {
//                docEnum = Tp_proctypeDocEnum.getByKey(proctype);
//            }
//            if (ObjectUtil.isNotNull(docEnum)) {
//                List<Tp_procmaterialEnum> procmaterials = docEnum.getProcmaterials();
//                for (Tp_procmaterialEnum procmaterial : procmaterials) {
//                    // 获取对应的applyid对应材料的记录
//                    List<Aprv_materials_options> optionList = this.aprv_materials_optionsService.findAllOptionsByMaterialType(applyid, procmaterial.getId());
//                    if (CollectionUtil.isNotEmpty(optionList)) {
//                        // 更新当前时间
//                        SimpleDateFormat format = new SimpleDateFormat("yyyy年M月d日");
//                        String nowDate = format.format(new Date());
//                        for (Aprv_materials_options options : optionList) {
//                            String optionid = options.getId();
//                            Integer busiType = options.getProctype();
//                            Map<String, Object> docfield = JSON.parseObject(options.getDocfiled(), Map.class);
//                            docfield.put("today", nowDate);
//                            Ha_attachment attachment = this.previewDocSaveToPdf(options.getApplyid(), options.getMattype(), docfield);
//                            this.aprv_materials_optionsService.endOptionMaterial(attachment, applyid, optionid, busiType, docfield);
//                        }
//                    }
//                }
//            }
//        } catch (Exception e) {
//            log.error(e.getMessage());
//        }

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void templateStamp(String applyid, Integer proctype) {
        // 所有文书都要盖章
        try {
            List<Aprv_process_materials> materialsList = aprv_process_materialsService.getAllMaterialByApplyId(applyid);
            List<Aprv_process_materials> filterMaterialsList = CollUtil.isNotEmpty(materialsList) ? materialsList.stream().filter(el -> el.getType().equals(proctype) && el.getSign().equals(Tp_sign.UNSIGN)).collect(Collectors.toList()) : Collections.emptyList();
            if (CollUtil.isNotEmpty(filterMaterialsList)) {
                // 按照类型过滤
                List<String> attachmentIds = filterMaterialsList.stream().map(Aprv_process_materials::getAttachid).collect(Collectors.toList());
                List<Ha_attachment> attachmentList = ha_attachmentService.getByIds(attachmentIds);
                SimpleDateFormat format = new SimpleDateFormat("yyyy年M月d日");
                if (CollUtil.isNotEmpty(attachmentList)) {
                    // 进行程序转换
                    String finalApplyid = applyid;
                    attachmentList.forEach(attachment -> {
                        if (attachment.getFilename().endsWith(".wps") || attachment.getFilename().endsWith(".WPS") || attachment.getFilename().endsWith(".doc") || attachment.getFilename().endsWith(".DOC")
                                || attachment.getFilename().endsWith(".docx") || attachment.getFilename().endsWith(".DOCX") || attachment.getPath().endsWith(".pdf") || attachment.getPath().endsWith(".PDF")) {
                            // 将文件转换为pdf
                            // 获取二进制流
                            InputStream inputStream = fileService.getStream(attachment.getBucket(), attachment.getPath());
                            // 转换为对应的文档
                            byte[] pdfByte = new byte[1024];
                            if (attachment.getFilename().endsWith(".wps") || attachment.getFilename().endsWith(".WPS") || attachment.getFilename().endsWith(".doc") || attachment.getFilename().endsWith(".DOC")
                                    || attachment.getFilename().endsWith(".docx") || attachment.getFilename().endsWith(".DOCX")) {
//                                try {
//                                    MultipartFile multipartFile = new MockMultipartFile(attachment.getFilename(), attachment.getFilename(), String.valueOf(ContentType.APPLICATION_JSON), inputStream);
//                                    pdfByte = this.fileTransFeign.word2pdf(multipartFile);
//                                    log.info("转换后文件大小 {}", ObjectUtil.isNotEmpty(pdfByte) ? pdfByte.length: "nul`");
//                                } catch (IOException e) {
//                                    throw new RuntimeException(e);
//                                }
                                pdfByte = PdfConvertUtil.word2pdfWithFont(inputStream);
                            } else {
                                ByteArrayOutputStream buffer = null;
                                try {
                                    buffer = new ByteArrayOutputStream();
                                    int nRead;
                                    while ((nRead = inputStream.read(pdfByte, 0, pdfByte.length)) != -1) {
                                        buffer.write(pdfByte, 0, nRead);
                                    }
                                    buffer.flush();
                                    pdfByte = buffer.toByteArray();
                                    buffer.close();
                                } catch (IOException e) {
                                    log.error("{}盖章文件inputstream流转换为pdf异常{}", attachment.getFilename(), e.getMessage());
                                }
                            }
                            try {
                                // 识别文本里是否有 （用印） 这两个字
                                InputStream pdfInputStream = new ByteArrayInputStream(pdfByte);
                                //multipartFile为multipartFile文件类型，将文件转化为文件流被PDDocument加载
                                PDDocument document = PDDocument.load(pdfInputStream);
                                document.getClass();
                                //使用PDFTextStripper 工具
                                PDFTextStripper tStripper = new PDFTextStripper();
                                //设置文本排序，有规则输出
                                tStripper.setSortByPosition(true);
                                //获取所有文字信息
                                String info = tStripper.getText(document);
                                log.info("{}盖章文件文本内容为{}", attachment.getFilename(), info);
                                if (StringUtils.isNotEmpty(info) && info.indexOf(SIGN_TEXT) > 0) {
                                    String[] newFileNames = attachment.getFilename().split("\\.");
                                    if (ObjectUtil.isNotEmpty(newFileNames) && newFileNames.length > 1 && ObjectUtil.isNotNull(pdfByte)) {
                                        String firstName = newFileNames[0] + "(盖章)";
                                        final String endName = ".pdf";
                                        final String newFileName = firstName + endName;
                                        Aprv_process_materials materials = filterMaterialsList.stream().filter(el -> el.getAttachid().equals(attachment.getId())).findAny().orElse(null);

                                        if (ObjectUtil.isNotEmpty(materials) && ObjectUtil.isNotEmpty(materials.getCreatetime())) {
                                            Ha_attachment newAttachment = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), newFileName);
                                            Aprv_process_materials newMaterials = BeanUtil.copyProperties(materials, Aprv_process_materials.class);
                                            String key = materials.getApplyid() + NanoIdUtils.randomNanoId();
                                            newMaterials.setId(key);
                                            newMaterials.setAttachid(newAttachment.getId());
                                            newMaterials.setCreatetime(new Date());
                                            newMaterials.setSign(Tp_sign.SIGNED);
                                            aprv_process_materialsService.saveOrUpdate(newMaterials);
                                            materials.setSign(Tp_sign.SIGNSOURCE);
                                            aprv_process_materialsService.saveOrUpdate(materials);
                                            String createDate = format.format(materials.getCreatetime());
                                            cloud_sign_licenseService.saveAdmreSign(finalApplyid, "/" + newAttachment.getPath(), createDate);
                                        }
                                    }
                                }
                            } catch (IOException e) {
                                log.error("{}盖章文件转pdf异常{}", attachment.getFilename(), e.getMessage());
                            }
                        }
                    });
                }
            }
        } catch (Exception e) {
            log.error("盖章文件转换异常{}", e.getMessage());
        }

    }

    @Override
    @Transactional(readOnly = true)
    public String computeExpiryDate(Integer apptype, String accepttime) {
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            // 计算天数从当前天数后一天开始计算
            Date acceptDate = format.parse(accepttime);
            Calendar cal = Calendar.getInstance();
            cal.setTime(acceptDate);
            acceptDate = cal.getTime();
            // 多加一天
            return this.businessApproveDao.expiryDate(acceptDate, Tp_apptype.EASY == apptype ? 31 : 61);
        } catch (Exception e) {
            log.error("computeExpiryDate 计算期满日期失败 ->  msg[{}]", e.getMessage());
            throw new RuntimeException("计算期满日期失败 -> " + e.getMessage());
        }
    }


    @Override
    public void transSignMaterial() {
        List<Cloud_sign_license> licenseList = cloud_sign_licenseService.findAll();
        if (CollectionUtil.isNotEmpty(licenseList)) {
            List<Cloud_sign_license> filterLicenseList = licenseList.stream().filter(el -> StringUtils.isNotEmpty(el.getFilepath()) &&
                    ((el.getFilepath().endsWith(".wps") || el.getFilepath().endsWith(".doc") || el.getFilepath().endsWith(".docx")
                            || el.getFilepath().endsWith(".WPS")) || el.getFilepath().endsWith(".DOC") || el.getFilepath().endsWith(".DOCX"))).collect(Collectors.toList());
            SimpleDateFormat format = new SimpleDateFormat("yyyy年M月d日");
            if (CollectionUtil.isNotEmpty(filterLicenseList)) {
                filterLicenseList.stream().forEach(el -> {
                    // 通过路径查询对应的材料记录
                    final String filePath = el.getFilepath().replaceFirst("/", "");
                    String attachmentId = this.aprv_process_materialsService.getAttachmentByPath(filePath);
                    List<Ha_attachment> attachmentList = ha_attachmentService.getByIds(Arrays.asList(attachmentId));
                    if (CollectionUtil.isNotEmpty(attachmentList)) {
                        attachmentList.stream().forEach(attachment -> {
                            if (attachment.getFilename().endsWith(".wps") || attachment.getFilename().endsWith(".WPS") || attachment.getFilename().endsWith(".doc") || attachment.getFilename().endsWith(".DOC")
                                    || attachment.getFilename().endsWith(".docx") || attachment.getFilename().endsWith(".DOCX")) {
                                // 获取二进制流
                                InputStream inputStream = fileService.getStream(attachment.getBucket(), attachment.getPath());
                                // 转换为对应的文档
                                byte[] pdfByte = PdfConvertUtil.word2pdfWithFont(inputStream);
                                String newFileName = attachment.getFilename().replace(".wps", ".pdf")
                                        .replace(".WPS", ".pdf").replace(".docx", ".pdf")
                                        .replace(".DOCX", ".pdf").replace(".doc", ".pdf").replace(".DOC", ".pdf");
                                // 查询对应的表记录
                                List<Aprv_process_materials> materialsList = this.aprv_process_materialsService.getAllMaterialByAttachId(attachmentId);
                                if (CollectionUtil.isNotEmpty(materialsList)) {
                                    materialsList.stream().forEach(material -> {
                                        if (ObjectUtil.isNotEmpty(material) && ObjectUtil.isNotEmpty(material.getCreatetime())) {
                                            try {
                                                Ha_attachment newAttachment = ha_attachmentService.upload(new ByteArrayInputStream(pdfByte), newFileName);
                                                Aprv_process_materials newMaterials = BeanUtil.copyProperties(material, Aprv_process_materials.class);
                                                String key = material.getApplyid() + NanoIdUtils.randomNanoId();
                                                newMaterials.setId(key);
                                                newMaterials.setAttachid(newAttachment.getId());
                                                newMaterials.setCreatetime(new Date());
                                                aprv_process_materialsService.saveOrUpdate(newMaterials);
                                                String createDate = format.format(material.getCreatetime());
                                                // 更新盖章文件地址
                                                el.setFilepath("/" + newAttachment.getPath());
                                                el.setCreatetime(new Date());
                                                cloud_sign_licenseService.saveOrUpdate(el);
                                            } catch (IOException e) {
                                                throw new RuntimeException(e);
                                            }
                                        }
                                    });
                                }
                            }

                        });
                    }
                });

            }

        }
    }

    @Override
    public void changeDecisionType(String f_applyid, String applyid, Integer decisiontype, Integer decisiontypeid, String decisiontypename) throws BusinessException {
        // 获取当前的子流程
        Apl_main sonApprove = this.apl_mainService.getById(applyid);
        if (ObjectUtil.isNotNull(sonApprove)) {
            // 获取当前的instid
            String soninstid = sonApprove.getInstid();
            List<Apl_admre_audit> auditList = this.apl_admre_auditService.listAdmreAuditByApplyid(f_applyid);
            if (CollectionUtil.isNotEmpty(auditList)) {
                auditList = auditList.stream().filter(el -> el.getType().equals(Tp_proctype.HEAR_DECISION)).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(auditList)) {
                    // 更新字段
                    auditList.stream().forEach(el -> {
                        el.setDecisiontype(decisiontype);
                        el.setDecisiontypeid(decisiontypeid);
                        el.setDecisiontypename(decisiontypename);
                    });
                    this.apl_admre_auditService.saveAll(auditList);
                    // 更新流程变量状态
                    Map<String, Object> variableMap = new HashMap<>(16);
                    variableMap.put("decisiontype", decisiontype);
                    variableMap.put("decisiontypeid", decisiontypeid);
                    variableMap.put("decisiontypename", decisiontypename);
                    ResponseDTO res = this.iPersonalFeign.saveVariable(soninstid, variableMap);
                    if (0 != res.getCode()) {
                        throw new RuntimeException(res.getMsg());
                    }
                }
            }
        } else {
            throw new BusinessException("流程数据查询为空");
        }
    }

}
